﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.Text;
using System.Threading;
using Microsoft.SharePoint;
using SJKP.PDFConversion.Service;

namespace SJKP.PDFConversion.Client
{
    /// <summary>
    /// Helper class used to initial calls to the OCRServiceApplication.
    /// </summary>
    public class OCRClientHelper
    {
        private SPServiceContext serviceContext;
        private static ChannelFactory<IOCRServiceContract> channelFactory;
        private static object channelFactoryLock = new object();


        public OCRClientHelper()
        {
            serviceContext = SPServiceContext.Current;
            if (serviceContext == null)
            {
                throw new InvalidOperationException("No service context found");
            }
        }

        public OCRClientHelper(SPServiceContext serviceContext)
        {
            if (serviceContext == null)
            {
                throw new ArgumentNullException("serviceContext");
            }

            this.serviceContext = serviceContext;
        }

        public byte[] ProcessPdf(byte[] bytes)
        {
            byte[] retur = null;
            OCRServiceApplicationProxy proxy = serviceContext.GetDefaultProxy(typeof (OCRServiceApplicationProxy)) as OCRServiceApplicationProxy;
            if (proxy == null)
                throw new InvalidOperationException("OCR Service application proxy not found");

            SPServiceLoadBalancer loadBalancer = proxy.LoadBalancer;
            if (loadBalancer == null)
                throw new InvalidOperationException("No load balancer found for OCR Service application");
            SPServiceLoadBalancerContext context = loadBalancer.BeginOperation();
            try
            {
                using (new SPServiceContextScope(serviceContext))
                {
                    IChannel channel = GetChannel(proxy, context.EndpointAddress) as IChannel;
                    if (channel != null)
                    {
                        try
                        {
                            retur = ((IOCRServiceContract) channel).ProcessPdf(bytes);
                            channel.Close();
                        }
                        finally
                        {
                            if (channel.State != CommunicationState.Closed)
                                channel.Abort();

                        }
                    }
                }
            }
            catch(SPEndpointAddressNotFoundException)
            {
                if (context != null)
                    context.Status = SPServiceLoadBalancerStatus.Failed;
            }
            catch(Exception ex)
            {
                throw;
            }
            finally
            {
                if (context != null)
                    context.EndOperation();
            }
            return retur;
        }

        private IOCRServiceContract GetChannel(OCRServiceApplicationProxy proxy, Uri endpointAddress)
        {

            if (channelFactory == null)
            {
                lock (channelFactoryLock)
                {
                    if (channelFactory == null)
                    {
                        channelFactory = new ConfigurationChannelFactory<IOCRServiceContract>("http", proxy.Configuration, null);
                        channelFactory.ConfigureCredentials(SPServiceAuthenticationMode.Claims);                        
                    }
                }
            }

            return channelFactory.CreateChannelAsProcess(new EndpointAddress(endpointAddress));
        }
    }
}
